package StatementsManager;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;
use encoding 'utf8';

use Try::Tiny;

use Database;
use Screen;
use StatementDto;
use StatementsUtils;

#liczba rekordow pobierana jednorazowo z tabeli z frazami
our $STATEMENTS_PACK_SIZE = 5;

#handler do bazy
our $db;

#globalna liczba obsluzonych fraz do celow statystycznych
our $totalStatementsManaged = 0;

#konstruktor
sub new {
	shift;
	my $self = {};
	bless $self;

	if(!$db) {
		$db = Database->new();
	}
	
	my @statements;
	$self->{statements} = \@statements; 
	
	return $self;
}

#pobiera z bazy danych liczbe fraz do pobrania
sub getStatementsNum {
	my $self = shift;	
	my $statementsNum = $db->getStatementsNumber();
}

#sprawdza czy w kolejce sa jeszcze jakies frazy
sub isNextStatement {
	my $self = shift;
	my $statementsRef = $self->{statements};
	if($statementsRef) {
		my @statements = @{$statementsRef};
		my $statementsNum = scalar(@statements);
		if($statementsNum > 0) {
			return 1;
		}
	}
	return 0;
}

#zwraca kolejna fraze do pobrania
sub getNextStatement {
	my $self = shift;
	try {
		my @statements = @{$self->{statements}};
		my $statementsNum = scalar(@statements);
		if($statementsNum == 0) {
			#jezeli nie ma to pobieramy nastepna paczke
			private_getStatementsPack($self);
		}
		
		@statements = @{$self->{statements}};
		$statementsNum = scalar(@statements);
		if($statementsNum > 0) {
			my $statementDto = shift(@statements);
			$self->{statements} = \@statements;
			$totalStatementsManaged++;
			return $statementDto;
		} else {
			Screen->printAndLogDebug('Nie ma juz wiecej fraz do pobrania');
			return undef;
		}
	} catch {
		my $e = $_;
		Screen->printAndLogError($e);
		return undef;
	};
}

#pobiera z bazy danych paczke fraz do pobrania
sub private_getStatementsPack {
	my $self = shift;
	my $statementsRef = $db->getStatementsPack($STATEMENTS_PACK_SIZE);
	$self->{statements} = $statementsRef;
}

#ustawia flage is_new na 0, wpisuje liczbe slow i wpisuje tokeny do odpowiedniej tabicy
sub updateStatementAfterCollect {
	my $self = shift;
	my $statementDto = shift;
	
	if($statementDto->getNewStatementId()) {
		#to znaczy, ze z tabeli new_statements trzeba usunac ten rekord, bo go juz zalatwilismy
		try {
			$db->removeNewStatement($statementDto->getNewStatementId());
		} catch {
			my $e = $_;
			Screen->printAndLogError($e);
		};
	}
	
	if($statementDto->getTokensNum()) {
		#update wiadomosci w tabeli statements
		$db->updateStatementAfterCollect($statementDto->getStatementId());
	} else {
		#wyciagniecie listy tokenow
		my $tokensRef = StatementsUtils->getTokens($statementDto->getStatement());
		my @tokens = @{$tokensRef};
		
		#update wiadomosci w tabeli statements
		$db->updateStatementAfterCollect($statementDto->getStatementId(), scalar(@tokens));
		
		#polaczenie tokenow ze statementem
		try {
			my $statementPos = 0;
			foreach my $token (@tokens) {
				my $tokenId = private_getTokenId($self, $token);
				$db->joinStatementWithToken($statementDto->getStatementId(), $tokenId, ++$statementPos);
				#i jeszcze polaczenie tokenu z jego lematem jesli jest
				try {
					my $lematWordIdsRef = $db->getLematWordIds($token);
					my @lematWordIds = @{$lematWordIdsRef};
					if(scalar(@lematWordIds) > 0) {
						#foreach, bo moze byc lematyzowalne niejednoznacznie
						foreach my $lematWordId (@lematWordIds) {
							$db->insertTokensLemats($tokenId, $lematWordId);
						}
					}
				} catch {
					my $e = $_;
					Screen->printAndLogError($e);
				};
			}
		} catch {
			my $e = $_;
			Screen->printAndLogError($e);
		};
	}
}

#zwraca identyfikator podanego tokena
sub private_getTokenId {
	my $self = shift;
	my $token = shift;
	my $tokenId = $db->selectTokenId($token);
	if(!$tokenId) {
		#jezeli nie ma jeszcze w bazie to wstawiamy nowy token
		$tokenId = $db->insertToken($token);
		if($tokenId) {
			Screen->printAndLogDebug('Dodano nowy token: ' . $token);
		} else {
			die('Nie udalo sie wstawic nowego tokena: ' . $token);
		}
	}
	return $tokenId;
}

sub getTotalStatementsManaged {
	return $totalStatementsManaged;
}

1;